package api

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"io"
	"nnxy-search-api/search-order-api/api"
	"nnxy-search-api/search-user-api/extends/jwtauth"
	"nnxy-search-api/search-user-api/global"
	"nnxy-search-api/search-user-api/global/response"
	status2 "nnxy-search-api/search-user-api/global/status"
	"nnxy-search-api/search-user-api/proto"
	"nnxy-search-api/search-user-api/utils"
	"nnxy-search-api/search-user-api/validator/forms"
	"strconv"
)

// 生成UserResponse 实例
func returnSysUserResponse(infoResponse *proto.SysUserInfo) *response.SysUserResponse {
	return &response.SysUserResponse{
		Id:       uint32(infoResponse.Id),
		Username: infoResponse.Username,
		NickName: infoResponse.Nickname,
	}
}

// AdminLogin 密码登录
func AdminLogin(c *gin.Context) {
	pwdLoginForm := forms.PasswordLoginSysForm{}
	// 绑定验证 Json
	if err := c.ShouldBindJSON(&pwdLoginForm); err != nil {
		if err == io.EOF {
			response.Fail(c, status2.InvalidParameter)
			return
		}
		errs := err.(validator.ValidationErrors)
		response.FailCodeMsg(c, status2.InvalidParameter, utils.GetFirstError(errs.Translate(global.Trans)))
		return
	}

	uInfo, err := global.SysUserSrvClient.GetUserByName(c, &proto.SysUserInfo{Username: pwdLoginForm.Username})
	if err != nil {
		// 没有查找到用户信息
		if s, ok := status.FromError(err); ok {
			switch s.Code() {
			case codes.NotFound:
				response.FailCodeMsg(c, status2.NotFoundUser, s.Message()) // 用户不存在
			default:
				response.FailCodeMsg(c, status2.Fail, s.Message()) // 操作失败
			}
			return
		}
		response.Fail(c, status2.Fail) // 操作失败
		return
	}
	if uInfo.Status != 1 {
		response.FailCodeMsg(c, status2.AuthFail, "用户已被禁用")
		return
	}
	// 验证密码
	if err := CheckSysUserPassword(c, uInfo.Username, pwdLoginForm.Password); err != nil {
		zap.S().Infof("验证密码异常%v", err)
		// 没有查找到信息
		if s, ok := status.FromError(err); ok {
			switch s.Code() {
			case codes.NotFound:
				response.FailCodeMsg(c, status2.NotFoundUser, s.Message()) // 用户不存在
			case codes.InvalidArgument:
				response.FailCodeMsg(c, status2.PasswordError, s.Message())
			default:
				response.FailCodeMsg(c, status2.Fail, s.Message()) // 操作失败
			}
			return
		}
		response.Fail(c, status2.Fail) // 操作失败
		return
	}
	j := jwtauth.NewJWT()
	claims := jwtauth.NewCustomClaimsDefault(uint(uInfo.Id), uInfo.Username, uInfo.Nickname, true)
	token, err := j.CreateToken(*claims)
	if err != nil {
		response.FailCodeMsg(c, status2.Fail, err.Error())
		return
	}
	rsp := response.SysUserTokenResponse{
		Id:       claims.Id,
		Username: claims.Username,
		NickName: claims.Nickname,
		Token:    token,
	}

	response.SuccessMsgData(c, "登录成功", rsp)
}

// CheckSysUserPassword 验证管理密码
func CheckSysUserPassword(ctx *gin.Context, username string, password string) (err error) {
	rsp, err := global.SysUserSrvClient.CheckPassword(ctx, &proto.SysUserInfo{Username: username, Password: password})
	if err == nil && rsp.Success {
		return nil
	}
	return err
}

// List  获取管理用户列表
func List(ctx *gin.Context) {
	pn := ctx.DefaultQuery("pn", "1")
	pnInt, _ := strconv.Atoi(pn)
	pSize := ctx.DefaultQuery("psize", "10")
	pSizeInt, _ := strconv.Atoi(pSize)
	pageInfo := proto.SysUserInfo{
		Page:  int32(pnInt),
		Limit: int32(pSizeInt),
	}
	if username := ctx.DefaultQuery("username", ""); username != "" {
		pageInfo.Username = username
	}
	if nickname := ctx.DefaultQuery("nickname", ""); nickname != "" {
		pageInfo.Nickname = nickname
	}
	rsp, err := global.SysUserSrvClient.GetUserList(context.Background(), &pageInfo)
	if err != nil {
		zap.S().Errorw("[GetUserList] 查询 [用户列表] 失败",
			"msg", err.Error())
		HandlerGrpcErrorToHttp(err, ctx)
		return
	}

	result := make([]response.SysUserResponse, 0)
	for _, user := range rsp.Data {
		u := response.SysUserResponse{
			Id:       uint32(user.Id),
			Username: user.Username,
			NickName: user.Nickname,
		}
		result = append(result, u)
	}
	response.SuccessData(ctx, result)
}

// New 添加管理用户
func New(c *gin.Context) {
	// 表单验证
	createUserInfo := forms.RegisterSysUserForm{}
	if err := c.ShouldBindJSON(&createUserInfo); err != nil {
		api.HandleValidatorError(err, c)
		return
	}

	cuInfo := proto.SysUserInfo{
		Username: createUserInfo.Username,
		Nickname: createUserInfo.Nickname,
		Password: createUserInfo.Password,
	}

	uInfo, err := global.SysUserSrvClient.CreateUser(context.Background(), &cuInfo)
	if err != nil {
		if gerr, ok := status.FromError(err); ok {
			switch gerr.Code() {
			case codes.AlreadyExists:
				response.FailCodeMsg(c, status2.AlreadyExists, gerr.Message()) // 用户已存在
			case codes.InvalidArgument:
				response.FailCodeMsg(c, status2.Fail, gerr.Message())
			default:
				response.FailCodeMsg(c, status2.Fail, gerr.Message())
			}
			return
		}
		response.Fail(c, status2.Fail) // 操作失败
		return
	}
	rsp := returnSysUserResponse(uInfo)
	response.SuccessData(c, rsp)

}

func Detail(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	rsp, err := global.SysUserSrvClient.GetUserById(context.Background(), &proto.SysUserInfo{Id: int64(id)})
	if err != nil {
		HandlerGrpcErrorToHttp(err, ctx)
		return
	}
	response.SuccessData(ctx, returnSysUserResponse(rsp))
}

func Update(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	createUserInfo := forms.RegisterSysUserForm{}
	if err := ctx.ShouldBindJSON(&createUserInfo); err != nil {
		api.HandleValidatorError(err, ctx)
		return
	}
	_, err := global.SysUserSrvClient.UpdateUser(context.Background(), &proto.SysUserInfo{Id: int64(id)})
	if err != nil {
		api.HandlerGrpcErrorToHttp(err, ctx)
		return
	}
	response.Success(ctx)
}

func Delete(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	_, err := global.SysUserSrvClient.DeleteUser(context.Background(), &proto.SysUserInfo{Id: int64(id)})
	if err != nil {
		HandlerGrpcErrorToHttp(err, ctx)
		return
	}
	response.Success(ctx)
}
